﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Globalization;

namespace sands
{
    public class Student
    {
        /* "Database structure"
         * Index
         * Imie
         * Nazwisko
         * Ulica
         * KodIMiasto
         * mobile number
         * home number
         * mums phone
         * dads phone
         * other
         */

        private String[] details;
        private int propertiesNum = 11;
        
        #region Properties
        public String Index
        {
            get
            {
                return details[0];
            }
            set
            {
                details[0] = value;
            }
        } //details[0]
        public String Surname
        {
            get
            {
                return details[2];
            }
            set
            {
                details[2] = value;
            }
        }
        public String FirstName
        {
            get
            {
                return details[1];
            }
            set
            {
                details[1] = value;
            }
        }
        public String ZipCity
        {
            get
            {
                return details[4];
            }
            set
            {
                details[4] = value;
            }
        }
        public String Street
        {
            get
            {
                return details[3];
            }
            set
            {
                details[3] = value;
            }

        }
        public String MobilePhone
        {
            get
            {
                return details[5];
            }
            set
            {
                details[5] = value;
            }
        }
        public String HomePhone
        {
            get
            {
                return details[6];
            }
            set
            {
                details[6] = value;
            }
        }
        public String MumsPhone
        {
            get
            {
                return details[7];
            }
            set
            {
                details[7] = value;
            }
        }
        public String DadsPhone
        {
            get
            {
                return details[8];
            }
            set
            {
                details[8] = value;
            }
        } //details[8]

        public bool isAdult
        {
            get
            {
                return details[propertiesNum-1].Contains("d");
            }
            set
            {
                if(details[propertiesNum-1]!=null)
                    if(details[propertiesNum-1].Contains("d"))
                        details[propertiesNum-1].Remove(details[propertiesNum-1].IndexOf("d"));

                if (value)
                    details[propertiesNum-1] += "d";
            }
        }      //d 2
        public bool isMatura
        {
            get
            {
                return details[propertiesNum-1].Contains("m");
            }
            set
            {
                if (details[propertiesNum-1] != null)
                    if (details[propertiesNum-1].Contains("m"))
                        details[propertiesNum-1].Remove(details[propertiesNum-1].IndexOf("m"));
                
                if (value)
                    details[propertiesNum-1] += "m";
            }
        }     //m 8
        public bool hasRates
        {
            get
            {
                return details[propertiesNum - 1].Contains("r");
            }
            set
            {
                if (details[propertiesNum - 1] != null)
                    if (details[propertiesNum - 1].Contains("r"))
                        details[propertiesNum - 1].Remove(details[propertiesNum - 1].IndexOf("r"));

                if (value)
                    details[propertiesNum - 1] += "r";
            }
        }     //r 9 !-10
        public String Discount      //z
        {
            get
            {
                if (details[propertiesNum - 1] != null)
                {
                    if (details[propertiesNum - 1].Contains("z"))
                    {
                        int start = details[propertiesNum - 1].IndexOf("z") + 2;
                        int end = details[propertiesNum - 1].IndexOf(")",start);

                        switch(details[propertiesNum - 1].Substring(start, end - start))
                        {
                            case "0":
                                return "1";
                            case "10":
                                return "0,9";
                            case "20":
                                return "0,81";
                            case "30":
                                return "0,729";
                        }
                    }
                    return String.Empty;
                }
                else
                    return String.Empty;

            }
            set
            {
                if (value != String.Empty)
                {
                    if (details[propertiesNum - 1] != null)
                        if (details[propertiesNum - 1].Contains("z"))
                        {
                            int start = details[propertiesNum - 1].IndexOf("z");
                            int end = details[propertiesNum - 1].IndexOf(")",start);

                            details[propertiesNum - 1].Remove(start, end - start);
                        }

                    details[propertiesNum - 1] += "z(" + value + ")";
                }
                else
                {
                    if (details[propertiesNum - 1] == null)
                        details[propertiesNum - 1] = String.Empty;
                }

            }
        }
        public String StartDate
        {
            get
            {
                return details[9];
            }
            set
            {
                details[9] = value;
            }
        }
        public int PayingOffset
        {
            get
            {
                int month = DateTime.Parse(StartDate).Month;
                if(month >= 9)
                    return DateTime.Parse(StartDate).Month - 9;
                else
                    return DateTime.Parse(StartDate).Month + 2;
            }
        }
        public String NewTuition
        {
            get
            {
                if (details[propertiesNum-1] != null)
                {
                    if (details[propertiesNum-1].Contains("t"))
                    {
                        int start = details[propertiesNum-1].IndexOf("t") + 2;
                        int end=details[propertiesNum-1].IndexOf(")",start);
                        

                        return details[propertiesNum-1].Substring(start, end - start);
                    }
                    return String.Empty;
                }    
                else
                    return String.Empty;

            }
            set
            {
                if (value != String.Empty)
                {
                    if (details[propertiesNum - 1] != null)
                        if (details[propertiesNum - 1].Contains("t"))
                        {
                            int start = details[propertiesNum - 1].IndexOf("t");
                            int end = details[propertiesNum - 1].IndexOf(")",start);

                            details[propertiesNum - 1].Remove(start, end - start);
                        }

                    details[propertiesNum - 1] += "t(" + value + ")";
                }
                else
                {
                    if(details[propertiesNum-1]==null)
                        details[propertiesNum - 1] = String.Empty;
                }

            }
        }

        public bool isLate
        {
            get
            {
                int[] convert = { 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4 }; //hpw many should have been paid in
                int ratesNum = DateTime.Now.Day < 15 ? convert[DateTime.Now.Month - 2 < 0 ? 4 : DateTime.Now.Month - 2] : convert[DateTime.Now.Month - 1];
                uint sum = 0;

                for (int i = 1; i <= ratesNum; ++i)
                    sum += (uint)GetRate((uint)i);

                if (GetPaidInSum() < sum)
                    return true;
                else
                    return false;
            }
        }
        #endregion

        public Student(String index, String surname, String firstName)
        {
            details = new String[propertiesNum];
            Index = index;
            Surname = surname;
            FirstName = firstName;
        }

        public Student(Object[] val)
        {
            details = new String[propertiesNum];
            Array.Copy(val, details, propertiesNum);
        }

        public String[] ToStringArray()
        {
            return details;
        }

        public bool CheckIfValid(bool edit)
        {
            String msg=""; //if empty
            String cor=""; // if not correct

            DataBase db = DataBase.GetInstance();

            if (Index.Equals(String.Empty))
                msg += "- Indeks\n";
            if(!edit)
                if ( ! db.isUnique(Index))
                    cor += "- Indeks (istnieje już uczeń o takim indeksie)\n";

            if (FirstName.Equals(String.Empty))
                msg += "- Imię\n";
            if (!Checker.isValidString(FirstName))
                cor += "- Imię (imię nie może zawierać znaków specjalnych)\n";

            if (Surname.Equals(String.Empty))
                msg += "- Nazwisko\n";
            if (!Checker.isValidString(Surname))
                cor += "- Nazwisko (imię nie może zawierać znaków specjalnych)\n";

            if (ZipCity.Equals(String.Empty))
                msg += "- Kod pocztowy i miasto\n";

            if(Street.Equals(String.Empty))
                msg += "- Ulica\n";

            if (MobilePhone.Equals(String.Empty) && HomePhone.Equals(String.Empty))
                msg += "- Telefon komórkowy lub telefon domowy\n";
            if (!Checker.isNumber(MobilePhone))
                cor += "- Telefon komórkowy (telefon nie może zawierać liter)\n";
            if (!Checker.isNumber(HomePhone))
                cor += "- Telefon domowy (telefon nie może zawierać liter)\n";
            
            uint tmp=0;
            if(NewTuition.Length>0)
            if (!uint.TryParse(NewTuition, out tmp))
                    msg += "- Kwotę (tylko liczba całkowita dodatnia)";

            if (!isAdult)
            {
                if (MumsPhone.Equals(String.Empty) && DadsPhone.Equals(String.Empty))
                    msg += "- Telefon do co najmniej jednego z rodziców\n";
                if (!Checker.isNumber(MumsPhone))
                    cor += "- Telefon do mamy (telefon nie może zawierać liter)\n";
                if (!Checker.isNumber(DadsPhone))
                    cor += "- Telefon do taty (telefon nie może zawierać liter)\n";
            }
            if (msg.Length > 0 || cor.Length>0)
            {
                if(msg.Length>0)
                    msg = "Proszę uzupełnić następujące pola:\n" + msg;
                if(cor.Length>0)
                    cor = "\nProszę poprawić następujące pola:\n" + cor;

                System.Windows.Forms.MessageBox.Show(msg+cor, "Niepełne dane", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
                return false;
            }
            else
                return true;
        }

        public uint GetNumberOfRates()
        {
            //=========Setting rate count
            uint rateCount = 0;

            if (this.isAdult)
                rateCount = 2;
            else if (!this.isAdult)
                rateCount = 9;
            if (this.isMatura)
                rateCount = 8;
            if (!this.hasRates)
                rateCount = 1;

            //adjusting by starting month
            if (rateCount > 2)
                rateCount -= (uint)this.PayingOffset;

            return rateCount;
        }

        /// <summary>
        /// Gets the rate in the specified month
        /// </summary>
        /// <param name="rateNum"></param>
        /// <returns></returns>
        public uint GetRate(uint rateNum)
        {
            uint price = 0;
            uint totalCost = GetTotalCost();
            uint rateCount = GetNumberOfRates();

            //getting rate value
            price = (uint)(Math.Floor(totalCost / rateCount / 10.0) * 10);

            if (rateNum == 1)
            {
                return (uint)(totalCost - price * (rateCount - 1));
                //return (rateCount > 1) ? price : totalCost;
            }
            else
            {
                return price;
            }
        }

        public uint GetDeposit(uint rateNum)
        {
            DataRow[] deposits = DataBase.GetInstance().GetDeposits(this);
            if (deposits.Length >= rateNum)
            {
                uint pr = 0u;
                uint.TryParse(deposits[rateNum-1].ItemArray[deposits[0].ItemArray.Length - 1].ToString(), out pr);
                return pr;
            }
            else
                return 0;
        }

        /// <summary>
        /// Gets the total cost of the course
        /// </summary>
        /// <param name="bValue"></param>
        /// <returns></returns>
        public uint GetTotalCost()
        {
            uint totalCost = DataBase.GetInstance().BaseValue;

            totalCost = (uint)(Math.Round((totalCost * double.Parse(Discount))/10)*10);

            if(!hasRates)
                totalCost = (uint)(Math.Round((totalCost * 0.9) / 10) * 10);

            //if special price
            if (this.NewTuition != string.Empty)
            {
                totalCost = uint.Parse(this.NewTuition);
            }

            return totalCost;
        }

        public String[,] GetDepositSchedule()
        {
            String[,] res = new String[GetNumberOfRates(), 2];
            String[] months = { "października", "listopada", "grudnia", "stycznia", "lutego", "marca", "kwietnia", "maja", "czerwca" };
            DataRow[] deposits = DataBase.GetInstance().GetDeposits(this);

            //setting first columns and adding
            res[0,0] = "1. rata płatna po 1. lekcji";
            res[0, 1] = GetRate(1).ToString("c0");

            for (int i = 2; i <= GetNumberOfRates(); ++i)
            {
                res[i - 1, 0] = i + ". rata płatna do 15. " + months[i - 2 + PayingOffset];
                res[i - 1, 1] = GetRate((uint)i).ToString("c0");
            }

            return res;
        }

        public List<Deposit> GetDepositHistory()
        {
            List<Deposit> res = new List<Deposit>();
            int sum=0;

            foreach (DataRow dr in DataBase.GetInstance().GetDeposits(this))
            {
                res.Add(new Deposit(dr["Data"].ToString(), dr["Numer"].ToString(), dr["Tytul"].ToString(), int.Parse(dr["Kwota"].ToString()).ToString("c0")));
                sum += int.Parse(dr["Kwota"].ToString());
            }
            res.Add(new Deposit("","","Razem:",sum.ToString("c0")));

            return res;
        } 

        public uint GetPaidInSum()
        {
            uint sum = 0;

            foreach(DataRow deposit in DataBase.GetInstance().GetDeposits(this))
                sum += uint.Parse(deposit.ItemArray[4].ToString());

            return sum;
        }
    }
}
